home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Interactive Reference Guide / C-C++ Interactive Reference Guide.iso / c_ref / csource5 / 357_01 / cstar1.exe / REG.C < prev    next >
C/C++ Source or Header  |  1991-06-18  |  31KB  |  1,395 lines

  1. /*
  2.     C* -- Register allocation code.
  3.  
  4.     source: reg.c
  5.     started: August 4, 1986
  6.     version:
  7.         February 20, 1986
  8.         March 7, 1989
  9.  
  10.     PUBLIC DOMAIN SOFTWARE
  11.  
  12.     The CSTAR program was placed in    the public domain on June 15, 1991,
  13.     by its author and sole owner,
  14.  
  15.         Edward K. Ream
  16.         1617 Monroe Street
  17.         Madison, WI 53711
  18.         (608) 257-0802
  19.  
  20.     CSTAR may be used for any commercial or non-commercial purpose.
  21.  
  22.     See cstar.h or cstar.c for a DISCLAIMER OF WARRANTIES.
  23. */
  24. #include "cstar.h"
  25.  
  26. /*
  27.     NOTE:    For the time being, get_temp creates fresh nodes
  28.     every time.  Nodes have to be held through the completion of
  29.     the peephole phase, and it is NOT, repeat NOT, ok to change
  30.     them simply because gen_xxx has already been called on them!
  31. */
  32.  
  33. /*
  34.     AVAIL registers are not defined by the user or used as special regs.
  35.     FREE  registers are registers which may be used as temporaries.
  36.     USED  registers have been used since the last regs_init
  37.         such registers need to be saved and restored by the function.
  38. */
  39.  
  40. /*    Forward declarations of functions.    */
  41. static struct node *    get_bot();
  42. static int         get_free();
  43.  
  44. /* -----
  45. #enum(1, GET_A, GET_D, GET_S)
  46. ----- */
  47. #define GET_A 1
  48. #define GET_D 2
  49. #define GET_S 3
  50.  
  51. /* Define S stack, a simulation stack used to allocate registers. */
  52. #define SS_MAX 200
  53. extern int ss_count, ss_forks, ss_bot;
  54.  
  55. static struct node * s_stack[SS_MAX];
  56. static int sf_stack[SS_MAX];
  57.  
  58. /* Track the AVAILABLE registers, and which of them are FREE. */
  59. static int ga_avail [8];
  60. static int gd_avail [8];
  61.  
  62. extern int sa_avail [8];
  63. extern int sd_avail [8];
  64.  
  65. extern int sa_used [8];
  66. extern int sd_used [8];
  67.  
  68. static int sa_free [8];
  69. static int sd_free [8];
  70.  
  71.  
  72. /* Keep track of the number of registers in each set. */
  73. static int na_avail;
  74. static int nd_avail;
  75.  
  76. extern int na_free;
  77. extern int nd_free;
  78.  
  79. /*
  80.     Externally visible routines:
  81. */
  82. void        regs_clear    (void);
  83. unsigned long    pd_alloc    (struct type_node *t, int mode);
  84. struct node *    locn_xconst    (long value);
  85. struct node *    locn_dupl    (struct node *s);
  86. struct node *    locn_xdupl    (struct node *s);
  87. struct node *    locn_chmod    (struct node *loc, int mode);
  88. struct node *    locn_reg    (int reg);
  89. static int    get_free    (int sx_free[]);
  90. struct node *    get_temp    (struct node * loc);
  91. struct node *    get_dtemp    (void);
  92. struct node *    get_atemp    (void);
  93. void        free_temp    (struct node *loc);
  94. void        free_xtemp    (struct node *loc1, struct node *loc2);
  95. void        force_free    (int reg);
  96. void        push_scratch    (void);
  97. void        free_reg    (int reg);
  98. bool        alloc_reg    (int reg);
  99. void        regs_init    (void);
  100. void        free_all    (void);
  101. bool        is_equiv    (struct node *loc1, struct node *loc2);
  102. bool        is_cloc        (struct node * loc);
  103. struct node *    fix_cloc    (register struct node * loc);
  104. bool        is_zloc        (struct node * loc);
  105. bool        is_xloc        (struct node * loc);
  106. bool        is_xtloc    (struct node * loc);
  107. bool        is_aloc        (struct node * loc);
  108. bool        is_atloc    (struct node * loc);
  109. bool        is_atreg    (int reg);
  110. bool        is_dtreg    (int reg);
  111. bool        is_dloc        (struct node * loc);
  112. bool        is_dtloc    (struct node * loc);
  113. bool        has_dtreg    (struct node * loc);
  114. bool        has_atreg    (struct node * loc);
  115. bool        is_storloc    (struct node *p);
  116. void        ss_push        (struct node * loc);
  117. struct node *    ss_pop        (void);
  118. struct node *    ss_restore    (void);
  119.  
  120. /*
  121.     Internal routines:
  122. */
  123. static int        decl_reg    (struct st_node *id);
  124. static struct node *    get_bot        (int reg_type, int arg);
  125. static struct node **    find_rloc    (register int reg);
  126.  
  127. /*
  128.     Deallocate the local registers
  129. */
  130. void
  131. regs_clear(void)
  132. {
  133.     register int i;
  134.  
  135.     TICK("regs_clear");
  136.  
  137.     na_free = nd_free = 0;
  138.     for (i = 0; i < 8; i++) {
  139.         if (ga_avail[i]) {
  140.             na_avail++;
  141.         }
  142.         sa_avail[i] = sa_free[i] = ga_avail[i];
  143.         if (gd_avail[i]) {
  144.             nd_avail++;
  145.         }
  146.         sd_avail[i] = sd_free[i] = gd_avail[i];
  147.         sa_used[i] = sd_used[i] = FALSE;
  148.     }
  149.     na_free = na_avail;
  150.     nd_free = nd_avail;
  151.     /* NOTE: for this purpose, A6 and A7 do not show up as sa_used;
  152.        they are saved and restored independently of other regs */
  153. }
  154.         
  155. /*
  156.     Go through an ELEMENT list and do the offsets.
  157.  
  158.     See note in lint.c about folded variables.  Offsets are treated as
  159.     signed longs, and that may not be good enough for fully-stuffed
  160.     or virtual memory systems.
  161. */
  162. unsigned long
  163. pd_alloc(struct type_node *t, int mode)
  164. {
  165.     register struct type_node *t1;
  166.     register struct st_node *id;
  167.     register struct node *loc1, *loc3;
  168.     register long o, size;
  169.     register int reg;
  170.  
  171.     TRACEPB("pd_alloc", printf("(%p, %d)\n", t, mode));
  172.  
  173.     switch (mode) {
  174.     case 0:
  175.         /* formals */
  176.         o = 8;
  177.         break;
  178.  
  179.     case 1:
  180.         /* locals */
  181.         o = 0;
  182.         break;
  183.  
  184.     default:
  185.         /* all else */
  186.         o = 0;
  187.     }
  188.     size = o;
  189.  
  190.     while (t != NULL) {
  191.         TRACEP("pd_alloc", printf("doing node %p\n", t));
  192.                             
  193.         if (!is_element(t -> t_typtok)) {
  194.             t_error("pd_alloc: internal: not ELEMENT");
  195.             break;
  196.         }
  197.         id = t -> t_parent;
  198.         if (id == NULL) {
  199.             /* currently, pure tags have no parents */
  200.             t = t -> t_list;
  201.             continue;
  202.         }
  203.         t1 = t -> t_link;
  204.         if (t1 == NULL) {
  205.             t_error("pd_alloc: internal: typeless ELEMENT");
  206.             break;
  207.         }
  208.         switch (mode) {
  209.         case 0:
  210.             /* formals */
  211.             if (t1 -> t_tsize == 1) {
  212.                 /*
  213.                     byte size argument treated as
  214.                     interchangeable with int for
  215.                     compatibility
  216.                 */
  217.                 id -> st_offset = o + 1;
  218.                 o += 2;
  219.             }
  220.             else {
  221.                 /* word or long size argument */
  222.                 id -> st_offset = o;
  223.                 o += (long) t1 -> t_tsize;
  224.             }
  225. #ifdef DEBUG
  226.             if (t1 -> t_tsize == 3 || t1 -> t_tsize > 4) {
  227.                 t_error("formal has bad size");
  228.             }
  229. #endif /* DEBUG */
  230.  
  231.             if (id -> st_sclass == FORMREG_CLASS) {
  232.                 if (reg = decl_reg(id)) {
  233.                     TRACEP("pd_alloc", printf("formal register\n"););
  234.                     loc3 = locn_reg(reg);
  235.                     loc3 -> n_cltype = id -> st_type;
  236.                     loc1 = locn_xconst(id -> st_offset);
  237.                     loc1 -> n_reg1 = R_A6;
  238.                     loc1 -> n_mode = EA_MODE;
  239.                     g_2l2(X_MOVE, loc1, loc3);
  240.                 }
  241.                 else {
  242.                     id -> st_sclass = FORMAL_CLASS;
  243.                 }
  244.             }
  245.             break;
  246.         case 1:
  247.             /* locals */
  248.             switch (id -> st_sclass) {
  249.             case REGISTER_CLASS:
  250.                 if (decl_reg(id)) {
  251.                     id -> st_offset = 0;
  252.                     break;
  253.                 }
  254.                 else {
  255.                     id -> st_sclass = AUTO_CLASS;
  256.                 }
  257.                 /* FALL_THROUGH */
  258.                 
  259.             case AUTO_CLASS:
  260.                 o -= (long) t1 -> t_tsize;
  261.                 /* keep start of larger objects on even boundary */
  262.                 if ((o & 1) && t1 -> t_tsize > 1) {
  263.                     o--;
  264.                 }
  265.                 id -> st_offset = o;
  266.                 break;
  267.             }
  268.             break;
  269.         case 2:
  270.             /* elements of structures */
  271.             /* keep start of larger objects on even boundary */
  272.             if ((o & 1) && t1 -> t_tsize > 1) {
  273.                 if (t1 -> t_typtok == ARRAY_TYPE &&
  274.                     t1 -> t_tsize == t1 -> t_tdim) {
  275.                     /* don't mess with boundary for
  276.                         array of bytes */
  277.                 }
  278.                 else {
  279.                     o++;
  280.                 }
  281.             }
  282.             id -> st_offset = o;
  283.             o += (long) t1 -> t_tsize;
  284.             break;
  285.         case 3:
  286.             /* elements of unions */
  287.             id -> st_offset = 0;
  288.  
  289.             /* WARNING: see note above about variables without sign: */
  290.             if (t1 -> t_tsize > (unsigned long) o) {
  291.                 o = t1 -> t_tsize;
  292.             }
  293.             break;
  294.         }
  295.         t = t -> t_list;
  296.     }
  297.     size -= o;    /* this is the change in o */
  298.  
  299.     /* WARNING: see note above about variables without sign: */
  300.     if (size < 0) {
  301.         size = -size;
  302.     }
  303.  
  304.     /* WARNING: see note above about variables without sign: */
  305.     if (size > 1 && (size & 1)) {
  306.         size += 1;    /* effect: treat all non-characters as being
  307.                    of even size; this way something like
  308.                    byte *p; p = p + sizeof(aggregate);
  309.                    will work properly */
  310.     }
  311.     RETURN_ULONG("pd_alloc", (unsigned long) size);
  312. }
  313.  
  314. /*
  315.     mark register unavailable and assign to st_node if necessary
  316. */
  317. static int
  318. decl_reg(struct st_node *id)
  319. {
  320.     register int i, j, reg;
  321.  
  322.     reg = id -> st_misc & ST_REG;    /* pick up manifest reg */
  323.  
  324.     TRACEPB("decl_reg", printf("reg = %d\n", reg));
  325.  
  326.     if (is_areg(reg)) {
  327.         /* Seize a specific A register--even a scratch register */
  328.         i = reg_idx(reg);
  329.         sa_free[i] = sa_avail[i] = FALSE;
  330.         sa_used[i] = TRUE;
  331.         TRACEP("decl_reg", printf("take manifest %s\n", arp_tab[reg]));
  332.         if (i < A_ALLOC) {
  333.             t_2help(arp_tab[reg], " is a scratch register");
  334.         }
  335.         RETURN_INT("decl_reg", reg);
  336.     }
  337.     else if (is_dreg(reg)) {
  338.         /* Seize a specific D register. */
  339.         i = reg_idx(reg);
  340.         sd_free[i] = sd_avail[i] = FALSE;
  341.         sd_used[i] = TRUE;
  342.         TRACEP("decl_reg", printf("take manifest %s\n", arp_tab[reg]));
  343.         if (i < D_ALLOC) {
  344.             t_2help(arp_tab[reg], " is a scratch register");
  345.         }
  346.         RETURN_INT("decl_reg", reg);
  347.     }
  348.  
  349.     if (id -> st_type -> t_typtok == INT_TYPE) {
  350.         /* Seize any D register among D2..D7 */
  351.         for (j = 7; j >= D_ALLOC; j--) {
  352.             if (sd_avail[j]) {
  353.                 id -> st_misc |= d_reg(j) & ST_REG;
  354.                 sd_avail[j] = FALSE;
  355.                 sd_used[j] = TRUE;
  356.                 TRACEP("decl_reg", printf("allocate reg %s\n",
  357.                             arp_tab[d_reg(j)]));
  358.                 RETURN_INT("decl_reg", d_reg(j));
  359.             }
  360.         }
  361.     }
  362.     else {
  363.         /* Seize any A register among A2..A5 */
  364.         for (j = 5; j >= A_ALLOC; j--) {
  365.             if (sa_avail[j]) {
  366.                 id -> st_misc |= a_reg(j) & ST_REG;
  367.                 sa_avail[j] = FALSE;
  368.                 sa_used[j] = TRUE;
  369.                 TRACEP("decl_reg", printf("allocate %s\n",
  370.                             arp_tab[a_reg(j)]));
  371.                 RETURN_INT("decl_reg", a_reg(j));
  372.             }
  373.         }
  374.     }
  375.     RETURN_INT("decl_reg", 0);
  376. }
  377.             
  378.  
  379.  
  380. /*
  381.     Return a constant node
  382. */
  383. struct node *
  384. locn_xconst(long value)
  385. {
  386.     TRACEPB("locn_xconst", printf("(%ld)\n", value));
  387.     RETURN_PTR("locn_xconst", new_cloc(value));
  388. }
  389.  
  390. /*
  391.     Make a new copy of a loc_node
  392. */
  393. struct node *
  394. locn_dupl(register struct node *s)
  395. {
  396.     register int i;
  397.     register struct node *r, *d;
  398.  
  399.     r = d = /* CAST(struct node *) */ new_pnode(sizeof(struct loc_node));
  400.  
  401.     TRACEPB("locn_dupl", printf("copy %p to %p\n", s, d));
  402.  
  403.     i = sizeof(struct loc_node)/sizeof(int);
  404.     while (i--) {
  405.         *((int *)d)++ = *((int *)s)++;
  406.     }
  407.     RETURN_PTR("locn_dupl", r);
  408. }
  409.  
  410. /*
  411.     Make a new copy of a loc_node if it is not marked
  412. */
  413. struct node *
  414. locn_xdupl(register struct node *s)
  415. {
  416.     register int i;
  417.     register struct node *r, *d;
  418.  
  419.     r = d = /* CAST(struct node *) */ new_pnode(sizeof(struct loc_node));
  420.  
  421.     TRACEPB("locn_xdupl", printf("copy %p to %p\n", s, d));
  422.  
  423.     i = sizeof(struct loc_node)/sizeof(int);
  424.     while (i--) {
  425.         *((int *)d)++ = *((int *)s)++;
  426.     }
  427.  
  428.     RETURN_PTR("locn_xdupl", r);
  429. }
  430.  
  431. /*
  432.     Change the mode of a loc_node by swapping if possible
  433.     Else by copying if marked
  434.     Else directly
  435.  
  436.     It is presumed that the mode does need changing
  437. */
  438. struct node *
  439. locn_chmod(struct node *loc, int mode)
  440. {
  441.     TRACEPB("locn_chmod", printf("(%p, %d)\n", loc, mode));
  442.  
  443.     loc = locn_dupl(loc);
  444.     loc -> n_mode = (byte) mode;
  445.  
  446.     RETURN_PTR("locn_chmod", loc);
  447. }
  448.  
  449. /*
  450.     Return a loc_node corresponding to the given register
  451.     field
  452.  
  453.     If the field corresponds to a temporary, do it by swapping
  454. */
  455. struct node *
  456. locn_reg(int reg)
  457. {
  458.     TRACEPB("locn_reg", printf("(%d)\n", reg));
  459.     RETURN_PTR("locn_reg", new_rloc(reg));
  460. }
  461.  
  462. /*
  463.     return index of free register
  464.     THIS DOES NOT CHANGE THE FREE ARRAY
  465. */
  466. static int
  467. get_free(int sx_free[])
  468. {
  469.     register int index;
  470.  
  471.     /* return lowest free register */
  472.  
  473.     TRACEPB("get_free", printf("(%p)\n", sx_free));
  474.  
  475.     for (index = 0; index <= 7; index++) {
  476.         if (sx_free[index]) {
  477.             RETURN_INT("get_free", index);
  478.         }
  479.     }
  480.     RETURN_INT("get_free", 0);
  481. }
  482.  
  483. /*
  484.     Return a pointer to a temporary register compatible with loc.
  485. */
  486. struct node *
  487. get_temp(struct node * loc)
  488. {
  489.     register struct node *p;
  490.  
  491.     TRACEPB("get_temp", printf("(%p)\n", loc));
  492.  
  493.     if (loc -> n_cltype -> t_typtok != INT_TYPE) {
  494.         p = get_atemp();
  495.     }
  496.     else {
  497.         p = get_dtemp();
  498.     }
  499.     p -> n_cltype = loc -> n_cltype;
  500.  
  501.     /* BUG FIX: */
  502.     RETURN_PTR("get_temp", p);
  503. }
  504.  
  505. /*
  506.     Return a pointer to a D temporary register
  507. */
  508. struct node *
  509. get_dtemp(void)
  510. {
  511.     struct node *p;
  512.     int index;
  513.  
  514.     /* Return a free D register. */
  515.  
  516.     TICKB("get_dtemp");
  517.  
  518.     if (nd_free) {
  519.         /* identify and take the free D register */
  520.         index = get_free(sd_free);
  521.         sd_free [index] = FALSE;
  522.         nd_free--;
  523.  
  524.         p = new_rloc(d_reg(index));
  525.         sd_used [index] = TRUE; /* sd_used is NOT related to sd_free */
  526.     }
  527.     else {
  528.         /* Push the bottom D reg and return it. */
  529.         p = get_bot(GET_D, 0);
  530.     }
  531.     TRACEP("get_dtemp",
  532.         printf("return %p: %d , %d free\n", p, p -> n_reg1, nd_free));
  533.  
  534.     RETURN_PTR("get_dtemp", p);
  535. }
  536.  
  537. /*
  538.     Return a pointer to an A temporary
  539. */
  540. struct node *
  541. get_atemp(void)
  542. {
  543.     register struct node *p;
  544.     register int index;
  545.  
  546.     TICKB("get_atemp");
  547.  
  548.     if (na_free) {
  549.         index = get_free(sa_free);
  550.         sa_free [index] = FALSE;
  551.         na_free--;
  552.         p = new_rloc(a_reg(index));
  553.         sa_used [index] = TRUE; /* sa_used is NOT related to sa_free */
  554.     }
  555.     else {
  556.         /* Push the bottom A reg and return it. */
  557.         p = get_bot(GET_A, 0);
  558.     }
  559.  
  560.     TRACEP("get_atemp",
  561.         printf("return %p: %d , %d free\n",
  562.             p, a_reg(index), na_free));
  563.  
  564.     RETURN_PTR("get_atemp", p);
  565. }
  566.  
  567. /*
  568.     Get a temporary by "pushing" a stack node; at least one item is
  569.     always "pushed".
  570.  
  571.     This is the only code that increases ss_bot.  ss_bot is then
  572.     decreased only by ss_pop.
  573.  
  574.     CAUTION: ss_bot is interrogated in g_2call and gen_args to determine
  575.     whether anything is on the physical stack, in order to disable the
  576.     use of nopush_loc if that is so.
  577.  
  578.     Nodes below ss_bot are already "pushed" in this sense.  The node
  579.     at ss_bot is examined for temporaries.  If it has any, it is pushed,
  580.     and they are freed.  If either temporary is of the requested
  581.     type, it is returned.  Otherwise the process repeats with the new
  582.     (incremented) ss_bot.
  583.  
  584.     If ss_bot is at or over the ss_forks threshold, nodes are resolved
  585.     prior to being pushed.  This is intended for nodes that are to
  586.     be retrieved by ss_pop() and used directly as operands.  If ss_bot
  587.     is below the ss_forks threshold, any temporary COMPONENTS are pushed
  588.     individually.  These nodes MUST be retrieved by ss_restore(); their
  589.     retrieval by ss_pop() is a fatal error.
  590.  
  591.     If a temporary is not found, a fatal error occurs.
  592.  
  593.     GET_S is used by push_scratch() for generating code that pushes
  594.     all the temporaries
  595. */
  596. static struct node *
  597. get_bot(int reg_type, int arg)
  598. {
  599.     register int reg, count;
  600.     register struct node *loc, *loci;
  601.  
  602.     TRACEPB("get_bot",
  603.         printf("(%d, %d)\n", reg_type, arg);
  604.         printf("entry: ss_count = %d, ss_bot = %d, ss_forks = %d\n",
  605.             ss_count, ss_bot, ss_forks));
  606.  
  607.     if (reg_type == GET_S) {
  608.         count = arg;
  609.     }
  610.     else {
  611.         count = ss_count;
  612.     }
  613.  
  614.     while (ss_bot < count) {
  615.         loc = s_stack[ss_bot];
  616.  
  617.         TRACEP("get_bot", pr_loc(loc);printf("\n"));
  618.  
  619.         sf_stack[ss_bot] = 0;
  620.  
  621.         if (ss_bot < ss_forks) {
  622.             /* in the forks case, save node and push components */
  623.             /* WARNING:
  624.                 if there are two components, it is not
  625.                 strictly necessary to save both of them.
  626.                 However, it simplifies the bookkeeping
  627.             */
  628.             if (reg = loc -> n_reg1) {
  629.                 if (is_atreg(reg) || is_dtreg(reg)) {
  630.                     /* mark r1 save */
  631.                     sf_stack[ss_bot] |= 0x801;
  632.                     loci = locn_reg(reg);
  633.                     loci -> n_cltype = long_type;
  634.                     g_2l1(X_MOVE, loci, push_loc);
  635.                 }
  636.                 if ((reg = loc -> n_reg2) &&
  637.                     (is_atreg(reg) || is_dtreg(reg))
  638.                                     ) {
  639.                     /* mark r2 save */
  640.                     sf_stack[ss_bot] |= 0x802;
  641.                     loci = locn_reg(reg);
  642.                     if (loc -> n_scflag == X2_WORD) {
  643.                         loci -> n_cltype = int_type;
  644.                     }
  645.                     else {
  646.                         loci -> n_cltype = long_type;
  647.                     }
  648.                     g_2l1(X_MOVE, loci, push_loc);
  649.                 }
  650.                 free_temp(loc);
  651.             }
  652.         }
  653.         else {
  654.             /* in the normal case, combine node to value and push */
  655.             /* caller routines will expect the value in pop_loc
  656.                         if it gets pushed */
  657.             if (loc = x_sspush(loc)) {
  658.                 s_stack[ss_bot] = loc;
  659.             }
  660.         }
  661.  
  662.         /* return if suitable register found */
  663.         if (reg_type == GET_A && na_free) {
  664.             ss_bot++;
  665.             RETURN_PTR("get_bot", get_atemp());
  666.         }
  667.         else if (reg_type == GET_D && nd_free) {
  668.             ss_bot++;
  669.             RETURN_PTR("get_bot", get_dtemp());
  670.         }
  671.         ss_bot++;
  672.     }
  673.     if (reg_type == GET_S) {
  674.         RETURN_PTR("get_bot", NULL);
  675.     }
  676.     else {
  677.         fatal("cannot get temporary");
  678.     }
  679.  
  680.     TICKX("get_bot");
  681. }
  682.  
  683.  
  684. /*
  685.     Find out whether any s_stack entry contains reg, regardless of
  686.     mode
  687. */
  688. static struct node **
  689. find_rloc(register int reg)
  690. {
  691.     register int i, count;
  692.     register struct node **ptr, *loc;
  693.  
  694. #ifdef DEBUG
  695.     register struct node **ptr2;
  696. #endif
  697.  
  698.     TRACEPB("find_rloc", printf("(%d)\n", reg));
  699.  
  700.     count = ss_count;
  701.     ptr = &s_stack[0];
  702.     i = count;
  703.     while (i > 0) {
  704.         loc = *ptr;
  705.         if (loc -> n_reg1 == reg || loc -> n_reg2 == reg) {
  706.             break;
  707.         }
  708.         ptr++;
  709.         i--;
  710.     }
  711.     if (i == 0) {
  712.         RETURN_PTR("find_rloc", NULL);
  713.     }
  714.  
  715. #ifdef DEBUG
  716.     ptr2 = ptr + 1;
  717.     i--;
  718.     while (i > 0) {
  719.         if ((*ptr2) -> n_reg1 == reg || (*ptr2) -> n_reg2 == reg) {
  720.             g_error(NULL, "duplicate instance of register in s_stack");
  721.         }
  722.         i--;
  723.         ptr++;
  724.     }
  725. #endif /* DEBUG */
  726.  
  727.     RETURN_PTR("find_rloc", ptr);
  728. }
  729.  
  730. /*
  731.     free registers designated in loc if they are temps
  732.     that is, just mark them as free
  733. */
  734. void
  735. free_temp(register struct node *loc)
  736. {
  737.     register int reg;
  738.  
  739.     TRACEPB("free_temp", printf("(%p)\n", loc));
  740.  
  741.     free_reg(loc -> n_reg1);
  742.     free_reg(loc -> n_reg2);
  743.  
  744.     TICKX("free_temp");
  745. }
  746.  
  747. /*
  748.     free registers designated in loc1 if they are temps
  749.     and are not in loc2
  750. */
  751. void
  752. free_xtemp(register struct node *loc1, register struct node *loc2)
  753. {
  754.     register int reg;
  755.  
  756. #ifdef DEBUG
  757.  
  758.     TRACEPB("free_xtemp", printf("(%p, %p)\n", loc1, loc2));
  759.  
  760.     if (loc2 == NULL) {
  761.         g_error(NULL, "internal: free_xtemp: NULL exception loc");
  762.         free_temp(loc1);
  763.         RETURN_VOID("free_xtemp");
  764.     }
  765. #endif /* DEBUG */
  766.  
  767.     if (reg = loc1 -> n_reg1) {
  768.         if (reg != loc2 -> n_reg1 && reg != loc2 -> n_reg2) {
  769.             free_reg(reg);
  770.         }
  771.         if (reg = loc1 -> n_reg2) {
  772.             if (reg != loc2 -> n_reg1 && reg != loc2 -> n_reg2) {
  773.                 free_reg(reg);
  774.             }
  775.         }
  776.     }
  777.  
  778.     TICKX("free_xtemp");
  779. }
  780.  
  781. /*
  782.     IF the designated register appears IN THE S_STACK, get a
  783.     temporary of the same kind, move it to the temporary, and
  784.     update the s_stack item appropriately.  (Use locn_xdupl).
  785.     This does NOT free the register.
  786. */
  787. void
  788. force_free(register int reg)
  789. {
  790.     register struct node **s_loc, *loct;
  791.     register int reg2;
  792.  
  793.     TRACEPB("force_free", printf("(%d)\n", reg));
  794.  
  795.     if (s_loc = find_rloc(reg)) {
  796.         /* always move long; it takes the same time, and then we
  797.             are SURE it's ok */
  798.         /* nothing available to ss_push and donate to the pool */
  799.         if (is_areg(reg)) {
  800.             loct = get_atemp();
  801.         }
  802.         else {
  803.             loct = get_dtemp();
  804.         }
  805.         loct -> n_cltype = long_type;
  806.         g_2l2(X_MOVE, locn_reg(reg), loct);
  807.  
  808.         /* now alter the entry */
  809.         *s_loc = loct = locn_xdupl(*s_loc);
  810.         if (loct -> n_reg1 == reg) {
  811.             loct -> n_reg1 = loct -> n_reg1;
  812.         }
  813.         if (loct -> n_reg2 == reg) {
  814.             loct -> n_reg2 = loct -> n_reg1;
  815.         }
  816.     }
  817.  
  818.     TICKX("force_free");
  819. }
  820.  
  821. /*
  822.     going up from the bottom of the s_stack, push registers
  823.     as if doing free_temp, until such time as the scratch regs
  824.     are all pushed
  825. */
  826. void
  827. push_scratch(void)
  828. {
  829.     register int ss_ptr, reg;
  830.  
  831.     TICKB("push_scratch");
  832.  
  833.     for (ss_ptr = ss_count - 1; ss_ptr >= 0; ss_ptr--) {
  834.         reg = s_stack[ss_ptr] -> n_reg1;
  835.         if (reg) {
  836.             if((is_areg(reg) && reg_idx(reg) <= ASCRATCH) ||
  837.                     reg_idx(reg) <= DSCRATCH) {
  838.                 break;
  839.             }
  840.             reg = s_stack[ss_ptr] -> n_reg2;
  841.             if((is_areg(reg) && reg_idx(reg) <= ASCRATCH) ||
  842.                     reg_idx(reg) <= DSCRATCH) {
  843.                 break;
  844.             }
  845.         }
  846.     }
  847.     if (ss_ptr < 0) {
  848.         RETURN_VOID("push_scratch");
  849.     }
  850.     (void) get_bot(GET_S, ss_ptr + 1);
  851.  
  852.     TICKX("push_scratch");
  853. }
  854.  
  855. /*
  856.     free a register if it turns out to be a temp
  857. */
  858. void
  859. free_reg(register int reg)
  860. {
  861.     register int i;
  862.  
  863.     TRACEPB("free_reg", printf("(%d)\n", reg));
  864.  
  865.     if (!reg) {
  866.         RETURN_VOID("free_reg");
  867.     }
  868.     i = reg_idx(reg);
  869.     if (is_areg(reg)) {
  870.         /* Free an A register. */
  871.         if (sa_avail[i] && !sa_free[i]) {
  872.             sa_free[i] = TRUE;
  873.             na_free++;
  874.             TRACE("free_reg",
  875.                 printf("free_reg: free A reg: na_free = %d\n",
  876.                                 na_free));
  877.         }
  878.     }
  879.     else {
  880.         /* Free a D register. */
  881.         if (sd_avail[i] && !sd_free[i]) {
  882.             sd_free[i] = TRUE;
  883.             nd_free++;
  884.             TRACE("free_reg",
  885.                 printf("free_reg: free D reg: nd_free = %d\n",
  886.                                 nd_free));
  887.         }
  888.     }
  889.  
  890.     TICKX("free_reg");
  891. }
  892.  
  893. /*
  894.     allocate a specific register as a temp if it is available
  895.     behavior is similar to get_temp, but without a search
  896.  
  897.     this is used, e.g. in sop_ternop
  898. */
  899. bool
  900. alloc_reg(register int reg)
  901. {
  902.     register int i;
  903.  
  904.     TRACEPB("alloc_reg", printf("(%d)\n", reg));
  905.  
  906.     if (!reg) {
  907.         RETURN_BOOL("alloc_reg", FALSE);
  908.     }
  909.     i = reg_idx(reg);
  910.     if (is_areg(reg)) {
  911.         /* Seize an A register. */
  912.         if (sa_avail[i] && sa_free[i]) {
  913.             sa_free[i] = FALSE;
  914.             sa_used[i] = TRUE;
  915.             na_free--;
  916.             TRACE("alloc_reg",
  917.                 printf("alloc_reg: seize A reg: na_free = %d\n",
  918.                                 na_free));
  919.             RETURN_BOOL("alloc_reg", TRUE);
  920.         }
  921.     }
  922.     else {
  923.         /* Seize a D register. */
  924.         if (sd_avail[i] && sd_free[i]) {
  925.             sd_free[i] = FALSE;
  926.             sd_used[i] = TRUE;
  927.             nd_free--;
  928.             TRACE("alloc_reg",
  929.                 printf("alloc_reg: seize D reg: nd_free = %d\n",
  930.                                 nd_free));
  931.             RETURN_BOOL("alloc_reg", TRUE);
  932.         }
  933.     }
  934.     RETURN_BOOL("alloc_reg", FALSE);
  935. }
  936.  
  937.  
  938. void
  939. regs_init(void)
  940. {
  941.     int i, na_max, nd_max;
  942.  
  943.     TICK("regs_init");
  944.  
  945.     /* WARNING: must set this up from symbol table somehow */
  946.     na_max = 6;    /* always exclude a6, a7 */
  947.     nd_max = 8;
  948.  
  949.     /* set up global availabilities */
  950.     for (i = 0; i < nd_max; i++) {
  951.         gd_avail [i] = TRUE;
  952.     }
  953.     for (; i < 8; i++) {
  954.         gd_avail [i] = TRUE;
  955.     }
  956.  
  957.     for (i = 0; i < na_max; i++) {
  958.         ga_avail [i] = TRUE;
  959.     }
  960.     for (; i < 6; i++) {
  961.         ga_avail [i] = TRUE;
  962.     }
  963.     for (; i < 8; i++) {
  964.         ga_avail [i] = FALSE;
  965.     }
  966.  
  967.     /* set up local availabilities */
  968.     regs_clear();
  969.  
  970.     /* NOTE: this better not be returned by anything since it's a push */
  971.     a0_loc = new_grloc(R_A0);
  972.     d0_loc = new_grloc(R_D0);
  973.     a6_loc = new_grloc(R_A6);
  974.     a7_loc = new_grloc(R_A7);
  975.     sr_loc = new_grloc(R_SR);
  976.     ccr_loc = new_grloc(R_CCR);
  977.  
  978.     push_loc = new_grloc(R_A7);
  979.     push_loc -> n_mode = EAPRD_MODE;
  980.  
  981.     nopush_loc = new_grloc(R_A7);
  982.     nopush_loc -> n_mode = EA_MODE;
  983.  
  984.     pop_loc = new_grloc(R_A7);
  985.     pop_loc -> n_mode = EAPSI_MODE;
  986.  
  987.     one_loc = new_grloc(0);
  988.     one_loc -> n_const = 1L;
  989.  
  990.     zero_loc = new_grloc(0);
  991. }
  992.  
  993. /*
  994.     Set all available regs to free and reset the pointers.
  995.     This should normally have no effect.
  996. */
  997. void
  998. free_all(void)
  999. {
  1000.     int i;
  1001.  
  1002.     TRACEP("free_all",
  1003.         printf("free_all entry: na_free %d, nd_free %d\n",
  1004.             na_free, nd_free));
  1005.  
  1006.     na_free = nd_free = 0;
  1007.     for (i = 0; i < 8; i++) {
  1008.         /* not == */
  1009.         if (sa_free[i] = sa_avail[i]) {
  1010.             na_free++;
  1011.         }
  1012.         if (sd_free[i] = sd_avail[i]) {
  1013.             nd_free++;
  1014.         }
  1015.     }
  1016.     ss_count = ss_bot = ss_forks = 0;
  1017. }
  1018.         
  1019. /*
  1020.     Return TRUE if loc1 is essentially equal to loc2 so that
  1021.     either can be used in place of the other.  Type is NOT
  1022.     checked and should be checked by the caller if required.
  1023. */
  1024. bool 
  1025. is_equiv(register struct node *loc1, register struct node *loc2)
  1026. {
  1027.     TRACEPB("is_equiv", printf("(%p, %p)\n", loc1, loc2));
  1028.  
  1029.     if (
  1030.         loc1 -> n_mode == loc2 -> n_mode && 
  1031.         loc1 -> n_cid == loc2 -> n_cid &&
  1032.         loc1 -> n_const == loc2 -> n_const &&
  1033.         loc1 -> n_reg1 == loc2 -> n_reg1 && 
  1034.         loc1 -> n_reg2 == loc2 -> n_reg2
  1035.                         ) {
  1036.         if (loc1 -> n_reg2) {
  1037.             RETURN_BOOL("is_equiv",
  1038.                 (loc1 -> n_scflag == loc2 -> n_scflag));
  1039.         }
  1040.         else {
  1041.             RETURN_BOOL("is_equiv", TRUE);
  1042.         }
  1043.     }
  1044.     RETURN_BOOL("is_equiv", FALSE);
  1045. }
  1046.             
  1047. /*
  1048.     Return TRUE if the loc node is a constant--that is, does
  1049.     not contain a register component or EA mode.
  1050. */
  1051. bool
  1052. is_cloc(struct node * loc)
  1053. {
  1054.     TRACEPB("is_cloc", printf("(%p)\n", loc));
  1055.  
  1056.     RETURN_BOOL("is_cloc",
  1057.         loc &&
  1058.         loc -> n_mode == VALUE_MODE &&
  1059.         loc -> n_reg1 == 0);
  1060. }
  1061.  
  1062. /*
  1063.     If the node is not a constant, return NULL.
  1064.  
  1065.     If the node is a global constant, return NULL.
  1066.  
  1067.     If the node is or can be made into a pure numeric constant, do so.
  1068.  
  1069.     Return a conditional copy of the node.
  1070. */
  1071. struct node *
  1072. fix_cloc(register struct node * loc)
  1073. {
  1074.     register int class;
  1075.  
  1076.     TRACEPB("fix_cloc", printf("(%p)\n", loc));
  1077.  
  1078.     if (loc -> n_reg1) {
  1079.         RETURN_PTR("fix_cloc", NULL);
  1080.     }
  1081.  
  1082.     class = loc -> n_cid -> st_sclass;
  1083.     if (loc -> n_cid) {
  1084.         if ( is_rstack(class) || class == SUE_CLASS ) {
  1085.             loc = locn_xdupl(loc);
  1086.             loc -> n_const += loc -> n_cid -> st_offset;
  1087.             loc -> n_cid = NULL;
  1088.         }
  1089.         else {
  1090.             RETURN_PTR("fix_cloc", NULL);
  1091.         }
  1092.     }
  1093.     else {
  1094.         loc = locn_xdupl(loc);
  1095.     }
  1096.     RETURN_PTR("fix_cloc", loc);
  1097. }
  1098.  
  1099. /*
  1100.     Return TRUE if the loc node represents absolute zero.
  1101. */
  1102. bool
  1103. is_zloc(struct node * loc)
  1104. {
  1105.     TRACEPB("is_zloc", printf("(%p)\n", loc));
  1106.  
  1107.     RETURN_BOOL("is_zloc",    loc &&
  1108.         loc -> n_mode == VALUE_MODE &&
  1109.         loc -> n_cid == NULL &&
  1110.         loc -> n_const == 0L &&
  1111.         loc -> n_reg1 == 0);
  1112. }
  1113.  
  1114. /*
  1115.     Return TRUE if the loc node represents any A or D register
  1116. */
  1117. bool
  1118. is_xloc(struct node * loc)
  1119. {
  1120.     TRACEPB("is_xloc", printf("(%p)\n", loc));
  1121.  
  1122.     RETURN_BOOL("is_xloc",    loc &&
  1123.         loc -> n_cid == 0 &&
  1124.         loc -> n_mode == VALUE_MODE &&
  1125.         is_xreg(loc -> n_reg1) &&
  1126.         loc -> n_reg2 == 0);
  1127. }
  1128.  
  1129. /*
  1130.     Return TRUE if the loc node represents any TEMPORARY register.
  1131. */
  1132. bool
  1133. is_xtloc(struct node * loc)
  1134. {
  1135.     TRACEPB("is_xtloc", printf("(%p)\n", loc));
  1136.  
  1137.     RETURN_BOOL("is_xtloc",    loc &&
  1138.         loc -> n_cid == NULL &&
  1139.         loc -> n_mode == VALUE_MODE &&
  1140.         is_xreg(loc -> n_reg1) &&
  1141.         loc -> n_reg2 == 0 &&
  1142.         (is_dreg(loc -> n_reg1) && sd_avail[reg_idx(loc -> n_reg1)] ||
  1143.          is_areg(loc -> n_reg1) && sa_avail[reg_idx(loc -> n_reg1)] ));
  1144. }
  1145.  
  1146. /*
  1147.     Return TRUE if the loc node represents ANY A register.
  1148. */
  1149. bool
  1150. is_aloc(struct node * loc)
  1151. {
  1152.     TRACEPB("is_aloc", printf("(%p)\n", loc));
  1153.  
  1154.     RETURN_BOOL("is_aloc",    loc &&
  1155.         loc -> n_cid == NULL &&
  1156.         loc -> n_mode == VALUE_MODE &&
  1157.         is_areg(loc -> n_reg1) &&
  1158.         loc -> n_reg2 == 0);
  1159. }
  1160.  
  1161. /*
  1162.     Return TRUE if loc node represents any A TEMPORARY register.
  1163. */
  1164. bool
  1165. is_atloc(struct node * loc)
  1166. {
  1167.     TRACEPB("is_atloc", printf("(%p)\n", loc));
  1168.  
  1169.     RETURN_BOOL("is_atloc",    loc &&
  1170.         loc -> n_cid == NULL &&
  1171.         loc -> n_mode == VALUE_MODE &&
  1172.         is_areg(loc -> n_reg1) &&
  1173.         loc -> n_reg2 == 0 &&
  1174.         sa_avail[reg_idx(loc -> n_reg1)]);
  1175. }
  1176.  
  1177. /*
  1178.     Return TRUE if designator designates any A TEMPORARY register.
  1179. */
  1180. bool
  1181. is_atreg(int reg)
  1182. {
  1183.     TRACEPB("is_atreg", printf("(%d)\n", reg));
  1184.  
  1185.     RETURN_BOOL("is_atreg",    is_areg(reg) &&
  1186.         sa_avail[reg_idx(reg)]);
  1187. }
  1188.  
  1189. /*
  1190.     Return TRUE if designator designates any D TEMPORARY register.
  1191. */
  1192. bool
  1193. is_dtreg(int reg)
  1194. {
  1195.     TRACEPB("is_dtreg", printf("(%d)\n", reg));
  1196.  
  1197.     RETURN_BOOL("is_dtreg",    is_dreg(reg) &&
  1198.         sd_avail[reg_idx(reg)]);
  1199. }
  1200.  
  1201. /*
  1202.     Return TRUE if loc node represents any D register.
  1203. */
  1204. bool
  1205. is_dloc(struct node * loc)
  1206. {
  1207.     TRACEPB("is_dloc", printf("(%p)\n", loc));
  1208.  
  1209.     RETURN_BOOL("is_dloc",    loc &&
  1210.         loc -> n_cid == NULL &&
  1211.         loc -> n_mode == VALUE_MODE &&
  1212.         is_dreg(loc -> n_reg1) &&
  1213.         loc -> n_reg2 == 0);
  1214. }
  1215.  
  1216. /*
  1217.     Return TRUE if loc node represents any D TEMPORARY register.
  1218. */
  1219. bool
  1220. is_dtloc(struct node * loc)
  1221. {
  1222.     TRACEPB("is_dtloc", printf("(%p)\n", loc));
  1223.  
  1224.     RETURN_BOOL("is_dtloc",    loc &&
  1225.         loc -> n_cid == NULL &&
  1226.         loc -> n_mode == VALUE_MODE &&
  1227.         is_dreg(loc -> n_reg1) &&
  1228.         loc -> n_reg2 == 0 &&
  1229.         sd_avail[reg_idx(loc -> n_reg1)]);
  1230. }
  1231.  
  1232. /*
  1233.     Return register designator if loc node contains any D TEMPORARY
  1234. */
  1235. int
  1236. has_dtreg(struct node * loc)
  1237. {
  1238.     TRACEPB("has_dtreg", printf("(%p)\n", loc));
  1239.  
  1240.     if (loc) {
  1241.         if ( is_dreg(loc -> n_reg1) &&
  1242.                      sd_avail[reg_idx(loc -> n_reg1)] ) {
  1243.             TRACEP("has_dtreg", printf("reg1: %d\n", loc -> n_reg1));
  1244.             RETURN_INT("has_dtreg", loc -> n_reg1);
  1245.         }
  1246.         else if ( is_dreg(loc -> n_reg2) &&
  1247.                     sd_avail[reg_idx(loc -> n_reg2)] ) {
  1248.  
  1249.             TRACEP("has_dtreg",
  1250.                 printf("reg1: %d\n", loc -> n_reg1));
  1251.  
  1252.             RETURN_INT("has_dtreg", loc -> n_reg2);
  1253.         }
  1254.     }
  1255.     RETURN_INT("has_dtreg", 0);
  1256. }
  1257.  
  1258. /*
  1259.     Return register designator if loc node contains any D TEMPORARY
  1260. */
  1261. int
  1262. has_atreg(struct node * loc)
  1263. {
  1264.     TRACEPB("has_atreg", printf("(%p)\n", loc));
  1265.  
  1266.     if (loc) {
  1267.         if ( is_areg(loc -> n_reg1) &&
  1268.                      sa_avail[reg_idx(loc -> n_reg1)] ) {
  1269.             TRACEP("has_atreg", printf("reg1: %d\n", loc -> n_reg1));
  1270.             RETURN_INT("has_atreg", loc -> n_reg1);
  1271.         }
  1272.         else if ( is_areg(loc -> n_reg2) &&
  1273.                     sa_avail[reg_idx(loc -> n_reg2)] ) {
  1274.             TRACEP("has_atreg", printf("reg2: %d\n", loc -> n_reg2));
  1275.             RETURN_INT("has_atreg", loc -> n_reg2);
  1276.         }
  1277.     }
  1278.     RETURN_INT("has_atreg", 0);
  1279. }
  1280.  
  1281. /*
  1282.     Return TRUE if loc_node could be valid destination for move
  1283. */
  1284. bool
  1285. is_storloc(struct node *p)
  1286. {
  1287.     TRACEPB("is_storloc", printf("(%p)\n", p));
  1288.  
  1289.     if (p -> n_mode == EA_MODE) {
  1290.         RETURN_BOOL("is_storloc", TRUE);
  1291.     }
  1292.     else if (p -> n_cid || p -> n_const) {
  1293.         RETURN_BOOL("is_storloc", FALSE);
  1294.     }
  1295.     else if (p -> n_reg1 && p -> n_reg2) {
  1296.         RETURN_BOOL("is_storloc", FALSE);
  1297.     }
  1298.     RETURN_BOOL("is_storloc", TRUE);
  1299. }
  1300.  
  1301. /*
  1302.     Push and pop values on the S stack.
  1303. */
  1304. void
  1305. ss_push(struct node * loc)
  1306. {
  1307.     TRACEPB("ss_push",
  1308.         printf("(%p)\n", loc);
  1309.         printf("%p: ", loc);
  1310.         pr_loc(loc); printf("\n");
  1311.         printf("new ss_count %d\n", ss_count+1));
  1312.  
  1313.     if (ss_count >= SS_MAX) {
  1314.         g_error(NULL, "code generator stack overflow");
  1315.     }
  1316.     else {
  1317.         s_stack [ss_count++] = loc;
  1318.     }
  1319.  
  1320.     TICKX("ss_push");
  1321. }
  1322.  
  1323. /* pop a node off the s_stack for use in an expression */
  1324. struct node *
  1325. ss_pop(void)
  1326. {
  1327.     TRACEPB("ss_pop",
  1328.         printf("entry: ss_count = %d, ss_bot = %d, ss_forks = %d\n",
  1329.             ss_count, ss_bot, ss_forks));
  1330.  
  1331.     if (ss_count <= 0) {
  1332.         fatal("code generator stack underflow");
  1333.     }
  1334.     else {
  1335.         TRACEP("ss_pop", printf("new ss_count %d\n", ss_count-1));
  1336.         if (--ss_count < ss_bot) {
  1337.             --ss_bot;
  1338. #ifdef DEBUG
  1339.             if (sf_stack[ss_bot]) {
  1340.                 fatal("ss_pop: internal: pops restore node");
  1341.             }
  1342. #endif /* DEBUG */
  1343.         }
  1344.         RETURN_PTR("ss_pop", s_stack [ss_count]);
  1345.     }
  1346.  
  1347.     TICKX("ss_pop");
  1348. }
  1349.  
  1350. /* restore a loc_node by popping its elements off the s_stack */
  1351. struct node *
  1352. ss_restore(void)
  1353. {
  1354.     register struct node *loc, *loci;
  1355.     register int flag;
  1356.  
  1357.     TRACEPB("ss_restore",
  1358.         printf("entry: ss_count = %d, ss_bot = %d, ss_forks = %d\n",
  1359.             ss_count, ss_bot, ss_forks));
  1360.  
  1361.     if (ss_bot <= 0) {
  1362.         fatal("ss_restore: underflow");
  1363.     }
  1364.  
  1365.     TRACEP("ss_restore", printf("new ss_bot %d\n", ss_bot-1));
  1366.  
  1367.     --ss_bot;
  1368.  
  1369.     loc = s_stack [ss_bot];
  1370.  
  1371.     /* restore components of node if pushed componentwise */
  1372.     flag = FALSE;
  1373.     if (sf_stack[ss_bot] & 1) {
  1374.         loci = locn_reg(loc -> n_reg1);
  1375.         loci -> n_cltype = long_type;
  1376.         g_2l2(X_MOVE, pop_loc, loci);
  1377.         (void) alloc_reg(loc -> n_reg1);
  1378.         flag = TRUE;
  1379.     }
  1380.     if (sf_stack[ss_bot] & 2) {
  1381.         loci = locn_reg(loc -> n_reg2);
  1382.         if (loci -> n_scflag == X2_WORD) {
  1383.             loci -> n_cltype = int_type;
  1384.         }
  1385.         else {
  1386.             loci -> n_cltype = long_type;
  1387.         }
  1388.         g_2l2(X_MOVE, pop_loc, loci);
  1389.         (void) alloc_reg(loc -> n_reg2);
  1390.         flag = TRUE;
  1391.     }
  1392.     sf_stack[ss_bot] = 0;
  1393.     RETURN_PTR("ss_restore", flag? loc : NULL);
  1394. }
  1395.